#include <am.h>
#include <klib-macros.h>
#include <riscv/riscv.h>
#include <klib.h>

extern char _bss_end;
extern char text_load_addr;
extern char _text_start;

extern char _heap_start;
extern char _heap_end;
int main(const char *args);

extern char _pmem_start;
#define PMEM_SIZE (128 * 1024 * 1024)
#define PMEM_END  ((uintptr_t)&_pmem_start + PMEM_SIZE)

// Area heap = RANGE(&_heap_start, PMEM_END);
Area heap = RANGE(&_heap_start, &_heap_end);
#ifndef MAINARGS
#define MAINARGS ""
#endif
static const char mainargs[] = MAINARGS;

void putch(char ch) {
  char empty;
  empty = inb(0x10000000L + 5) & 0b00100000;
  empty = empty >> 5;
  while (!empty) {
    empty = inb(0x10000000L + 5) & 0b00100000;
    empty = empty >> 5;
  }
  outb(0x10000000L, ch);
}

void halt(int code) {
  asm volatile("mv a0, %0; ebreak"::"r"(code));

  while (1);
}

void uart16550_init() {
  // outb(0x10000000L + 2, 0b1100110); // reset t/r fifo
  // outb(0x10000000L + 2, 0b1100000);
  outb(0x10000000L + 3, 0b10000011); // set line control register to access Divisor Latch

  outb(0x10000000L + 1, 0); // set MSB of devisor latch
  outb(0x10000000L, 10); // set LSB of devisor latch

  outb(0x10000000L + 3, 0b00000011); // set line control register to transmit data. 8N1
}

void info_cpu() {
  unsigned int mvendorid = 0;
  unsigned int marchid = 0;

  asm volatile("csrr %0, mvendorid" : "=r"(mvendorid));
  asm volatile("csrr %0, marchid" : "=r"(marchid));
  putch(mvendorid >> 24);
  putch((mvendorid & 0x00ff0000) >> 16);
  putch((mvendorid & 0x0000ff00) >> 8);
  putch(mvendorid & 0x000000ff);
  printf("%d\n", marchid);
}

// void bootloader() {
//   // memcpy(&_data_start, &data_load_addr, (size_t)(&_bss_end - &_data_start));
//   memcpy(&_text_start, &text_load_addr, (size_t)(&_bss_end - &_text_start));
// }

void _trm_init() {
  // bootloader();
  uart16550_init();
  info_cpu();

  int ret = main(mainargs);
  halt(ret);
}
